package protocol

import (
	"encoding/binary"
)

const (
	RESPSTATE_SIZE     = 4
	RESP_HEADER_LENGTH = PID_SIZE + SID_SIZE + RID_SIZE + TOKEN_SIZE + DS_SIZE + RESPSTATE_SIZE
)

type ResponseProtocolCodec struct{}

type Response_Header struct {
	ProviderID uint32
	ServiceID  uint32
	RequestID  uint32
	Token      uint32
	DataSize   uint32
	RESP_STATE uint32
}

// 0                                    32 bit
// +-------------------------------------+ -----
// |             Provider ID             |
// +-------------------------------------+
// |             Service  ID             |
// +-------------------------------------+
// |             Request  ID             |
// +-------------------------------------+  Header
// |          Validation Token           |
// +-------------------------------------+
// |              Data Size              |
// +-------------------------------------+
// |             RESP_STATE              |
// +-------------------------------------+ -----
// |          Response Content           |
// |                ...                  |  Body

func (codec *ResponseProtocolCodec) Decode(buf []byte) (respHeader Response_Header, data []byte, err error) {
	// 计算各个部分的偏移量
	pidOffset := 0
	sidOffset := pidOffset + PID_SIZE
	ridOffset := sidOffset + SID_SIZE
	tkOffset := ridOffset + RID_SIZE
	dsOffset := tkOffset + TOKEN_SIZE
	rsOffset := dsOffset + DS_SIZE
	dataOffset := rsOffset + RESPSTATE_SIZE

	// 提取Header
	respHeader.ProviderID = binary.BigEndian.Uint32(buf[pidOffset : pidOffset+PID_SIZE])
	respHeader.ServiceID = binary.BigEndian.Uint32(buf[sidOffset : sidOffset+SID_SIZE])
	respHeader.RequestID = binary.BigEndian.Uint32(buf[ridOffset : ridOffset+RID_SIZE])
	respHeader.Token = binary.BigEndian.Uint32(buf[tkOffset : tkOffset+TOKEN_SIZE])
	respHeader.DataSize = binary.BigEndian.Uint32(buf[dsOffset : dsOffset+DS_SIZE])
	respHeader.RESP_STATE = binary.BigEndian.Uint32(buf[rsOffset : rsOffset+RESPSTATE_SIZE])

	// 提取Body
	data = make([]byte, respHeader.DataSize)
	copy(data, buf[dataOffset:uint32(dataOffset)+respHeader.DataSize])

	err = nil
	return
}

func (codec *ResponseProtocolCodec) getHeader(respHeader Response_Header) (header []byte, err error) {
	header = make([]byte, 0)

	header = binary.BigEndian.AppendUint32(header, respHeader.ProviderID)
	header = binary.BigEndian.AppendUint32(header, respHeader.ServiceID)
	header = binary.BigEndian.AppendUint32(header, respHeader.RequestID)
	header = binary.BigEndian.AppendUint32(header, respHeader.Token)
	header = binary.BigEndian.AppendUint32(header, respHeader.DataSize)
	header = binary.BigEndian.AppendUint32(header, respHeader.RESP_STATE)

	err = nil
	return
}

func (codec *ResponseProtocolCodec) AppendHeader(respHeader Response_Header, body []byte) (res []byte, err error) {
	body_length := len(body)
	respHeader.DataSize = uint32(body_length)
	res = make([]byte, RESP_HEADER_LENGTH+body_length)
	header, _ := codec.getHeader(respHeader)
	copy(res[:REQ_HEADER_LENGTH], header[:])
	copy(res[REQ_HEADER_LENGTH:], body[:])

	err = nil
	return
}
